#include "stdafx.h"
#include "System.h"
#include "IWindow.h"
#include "Timer.h"
#include "Console.h"
#include "Profiler.h"
#include "Log.h"


CSystem::CSystem()
: m_pWindow(nullptr)
, m_pTimer(nullptr)
, m_pConsole(nullptr)
, m_pProfiler(nullptr)
, m_pLog(nullptr)
, m_bNeedShutdown(false)
{
	memset(&m_Env, 0, sizeof(m_Env));
}

CSystem::~CSystem()
{
	m_Env.pInput->UnregisterListener(m_pConsole);

	//	destroy game modules instances
	delete m_Env.pRender;
	delete m_Env.pInput;

	//	destroy window
	delete m_pWindow;

	//	destroy global systems
	delete m_pTimer;
	delete m_pConsole;
	delete m_pProfiler;
	delete m_pLog;
}

bool CSystem::Init()
{
	//	init environment variable
	gEnv = &m_Env;

	//	create core systems
	m_pTimer = new CTimer;
	m_pConsole = new CConsole;
	m_pProfiler = new CProfiler;
	m_pLog = new CLog(m_pConsole);

	//	init global pointers
	m_Env.pSystem = this;
	m_Env.pTimer = m_pTimer;
	m_Env.pConsole = m_pConsole;

	//	init filesystem base dir
	const char* exe_path = XApi::GetApplicationPath();
	string exe_dir = path_utils::get_directory(exe_path);
	string current_directory = exe_dir + "..";
	XApi::SetCurrentDirectory(current_directory.c_str());

	//	create window
	m_pWindow = XApi::CreateWindowX(gStartupParams->AppHandle, gStartupParams->MsgProc);
	if (!m_pWindow)
		return false;

	m_pWindow->SetCaption(gStartupParams->WindowCaption);
	m_pWindow->SetSize(gStartupParams->WindowWidth, gStartupParams->WindowHeight);
	m_pWindow->CenterScreen();

	//	load game modules
	m_Env.pRender = LoadGameModule<IRender>(DX9_RENDER_LIB_NAME);
	if (!m_Env.pRender)
		return false;

	m_Env.pInput = LoadGameModule<IInput>(INPUT_LIB_NAME);
	if (!m_Env.pInput)
		return false;

	//	
	m_Env.pInput->RegisterListener(m_pConsole);

	return true;
}

void CSystem::Shutdown()
{
	m_bNeedShutdown = true;
}

bool CSystem::IsShuttingDown() const
{
	return m_bNeedShutdown;
}

SGlobalEnvironment* CSystem::GetGlobalEnvironment()
{
	return &m_Env;
}

IWindow* CSystem::GetWindow()
{
	return m_pWindow;
}

ITimer* CSystem::GetTimer()
{
	return m_Env.pTimer;
}

ILog* CSystem::GetLog()
{
	return m_pLog;
}

CProfiler* CSystem::GetProfiler()
{
	return m_pProfiler;
}

void CSystem::Update()
{
	PROFILE_FUNCTION();

	//	update time
	m_Env.pTimer->Update();

	//	update input
	m_Env.pInput->Update();

	//	update game modules
	m_Env.pRender->Update();

	//	render frame
	m_Env.pRender->PreRender();

	m_Env.pRender->Render();
	m_pProfiler->Render(m_Env.pRender);
	m_Env.pConsole->Render();

	m_Env.pRender->PostRender();

	//	update profiler
	m_pProfiler->Update();
}